﻿/*******************************************************************************
* file  : rsa key text
* creat : apleilx
* data  : 2017/03/02
		: 签名实际是对消息做hash类信息摘要运算，将摘要结果进行私匙加密
		: 然后将公匙、消息明文、和签名发给接收方。
		: 消息长度任意，签名长度同密匙。
*******************************************************************************/
#include "common.h"
#include "crc_ext.h"
#include "mbedtls/rsa.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "bsp_api.h"
#include "stdio_cfg.h"
#include "os_obj.h"
#include "sys_task.h"
#include "mbedtls/platform.h"
#include "mbedtls/bignum.h"

#define MBEDTLS_AES_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_MD_C
#define MBEDTLS_OID_C           // 开启OID数据结构块
#define MBEDTLS_BIGNUM_C 
#define MBEDTLS_GENPRIME 
#define MBEDTLS_RSA_C
#define MBEDTLS_PKCS1_V21
#define MBEDTLS_AES_ROM_TABLES


/*******************************************************************************
* @brief  par.
*******************************************************************************/
extern void * rsa_src, *rsa_enc, *rsa_dec;

#define DEV_RANDOM_THRESHOLD        32
int rsa_random_entropy_poll( void *, unsigned char *, size_t, size_t *);

void dump_rsa_key(mbedtls_rsa_context *ctx);

/*******************************************************************************
* @brief  pub enc.
* \param[in] none
* \retval: none
*******************************************************************************/
#define assert_exit(cond, ret) \
    do { if (!(cond)) { \
        printf("  !. assert: failed [line: %d, error: -0x%04X]\n", __LINE__, -ret); \
        goto cleanup; \
    } } while (0)

static void dump_buf(char *info, uint8_t *buf, uint32_t len)
{
    mbedtls_printf("%s", info);
    for (int i = 0; i < len; i++) {
        mbedtls_printf("%s%02X%s", i % 16 == 0 ? "\n     ":" ", 
                        buf[i], i == len - 1 ? "\n":"");
    }
}


int ras_key_sign(void)
{
    int ret = 0;
    uint8_t msg[512];
    uint8_t sign[2048/8];
    char *pers = "simple_rsa_sign";

    mbedtls_rsa_context ctx;
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;

    mbedtls_entropy_init(&entropy);
    mbedtls_ctr_drbg_init(&ctr_drbg);
	
	//RSA密钥对初始化       填充方式PSS,散列算法SHA256
    mbedtls_rsa_init(&ctx);

	// 填充方案OAEP //SHA256做散列算法
    mbedtls_rsa_set_padding(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
	
	// 随机数生成器
	ret = mbedtls_entropy_add_source( 
		&entropy, 
		rsa_random_entropy_poll,
		NULL, 
		DEV_RANDOM_THRESHOLD,
		MBEDTLS_ENTROPY_SOURCE_STRONG );
	
    ret = mbedtls_ctr_drbg_seed(
		&ctr_drbg, 
		mbedtls_entropy_func, 
		&entropy, 
		(const uint8_t *) pers, 
		strlen(pers));
	
    assert_exit(ret == 0, ret);
    mbedtls_printf("\n  . setup rng ... ok\n\n");
	
    //产生RSA密钥对
    mbedtls_printf("  ! RSA Generating large primes may take minutes! \n");
    ret = mbedtls_rsa_gen_key(
		&ctx, 
		mbedtls_ctr_drbg_random, 
		&ctr_drbg, 
		2048,		//RSA2048
		65537);		//公开指数
	
    assert_exit(ret == 0, ret);
    mbedtls_printf("  1. rsa generate keypair ... ok\n");
    dump_rsa_key(&ctx);
	
	loop_n(500) msg[index] = index; 
	
    //RSA用私钥签名 输出sig签名结果
	ret = mbedtls_rsa_pkcs1_sign(
		&ctx, 
		mbedtls_ctr_drbg_random, 
		&ctr_drbg, 
		MBEDTLS_MD_NONE,
		sizeof(msg), 
		msg, 
		sign);
   
    assert_exit(ret == 0, ret);
    dump_buf("  2. rsa generate signature:", sign, sizeof(sign));
	
	// memset(msg, 0, 100);
    //RSA公钥验签 返回0则验证成功
    ret = mbedtls_rsa_pkcs1_verify(
		&ctx,  
		MBEDTLS_MD_NONE, 
		sizeof(msg), 
		msg, 
		sign);
	
    assert_exit(ret == 0, ret);
    mbedtls_printf("  3. rsa verify signature ... ok\n\n");
	dump_buf("  4. rsa sign msg :", msg, sizeof(msg));
	
cleanup:
    mbedtls_rsa_free(&ctx);
    mbedtls_ctr_drbg_free(&ctr_drbg);
    mbedtls_entropy_free(&entropy);

    return ret;
}
